package com.jrtc.api.interceptor;

import com.auth0.jwt.JWT;
import com.jrtc.base.annotations.PassToken;
import com.jrtc.base.annotations.UserLoginToken;
import com.jrtc.base.config.LoginException;
import com.jrtc.base.util.IpUtil;
import com.jrtc.base.util.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

public class AuthenticationInterceptor implements HandlerInterceptor {

//    private static final Logger log= LoggerFactory.getLogger(TestServiceImpl.class);
    private static final IpUtil ipUtil=new IpUtil();
    @Autowired
    private RedisUtil redis;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
        String token = httpServletRequest.getHeader("token");// 从 http 请求头中取出 token

        // 如果不是映射到方法直接通过
        if(!(object instanceof HandlerMethod)){
            return true;
        }

        //开发阶段
//        if(1==1){
//            return true;
//        }

        HandlerMethod handlerMethod=(HandlerMethod)object;
        Method method=handlerMethod.getMethod();
        //检查是否有passToken注释，有则跳过认证
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }

        //检查有没有需要用户登录的注解
        if (method.isAnnotationPresent(UserLoginToken.class)) {
            UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
            if (userLoginToken.required()) {
                // 执行认证
                if (token == null) {
                    throw new LoginException("无有效token，请重新登录");
                }
                System.out.println("接收token:"+token);
                // 获取 token 中的account
                String account = "-1";
                try {
                    account=JWT.decode(token).getAudience().get(0);
                }catch (Exception e){

                }

                //从redis中获取token ip信息进行验证
                Object objectMap=redis.get("loginUser"+account);

                System.out.println("查询登录用户account===="+account);
                System.out.println("查询登录用户objectMap===="+objectMap);

                if (objectMap == null||account.equals("-1")) {
                    throw new LoginException("登录已过期，请重新登录");
                }
                Map<String,String> redisMap=(Map<String,String>)objectMap;
                String redisIp=redisMap.get("ip");
                String curIp=ipUtil.getIpAddr(httpServletRequest);

                System.out.println("redisIp:"+redisIp);
                System.out.println("curIp:"+curIp);
//                if(!redisIp.equals(curIp)){
//                    throw new LoginException("token已过期，请重新登录");
//                }

//                if(!token.equals(redisMap.get("token"))){
//                    throw new LoginException("登录已过期，请重新登录");
//                }
                //每操作一次，从新往redis中存一次刷新时间
                redis.set(account, objectMap, 60 * 60 * 24 * 7);

                return true;
            }
        }

        //打印请求日志
//        log.info("requestURL:{}",httpServletRequest.getRequestURL());
//        log.info("Method:{}",httpServletRequest.getMethod());
//        log.info("requestIP:{}",ipUtil.getIpAddr(httpServletRequest));
//        log.info("head:{}", JSONUtils.toJSONString(getHead(httpServletRequest)));
//        log.info("param:{}", JSONUtils.toJSONString(httpServletRequest.getParameterMap()));
        return true;
    }

    public static Map<String,Object> getHead(HttpServletRequest request){
        Map<String,Object> map = new HashMap<>();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()){
            String key = (String) headerNames.nextElement();
            map.put(key,request.getHeader(key));
        }
        return map;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    }
}
